<?php

namespace Biz\service;

use Biz\cache\GoodsBasicInfo as cGoodsBaseInfo;
use Biz\cache\GoodsExtendInfo as cGoodsExtendInfo;
use Biz\cache\SkuBase as cSkuBase;
use Biz\cache\WikiGoods as cWikiGoods;
use Biz\model\GoodsBasicInfo as mGoodsBasicInfo;
use Biz\model\GoodsExtendInfo as mGoodsExtendInfo;
use Biz\model\GoodsSku as mGoodsSku;
use Biz\model\ShopFavorite;
use Biz\model\trade\Cart;
use Biz\module\Packages\GoodsFormatInfo\Scene\Goods as fGoods;
use Biz\pockets\constInterface\ActivityInfo;
use Biz\pockets\constInterface\CategoryExtendInfo;
use Biz\pockets\constInterface\GoodsFields;
use Biz\service\activity\FullShipping as sFullShipping;
use Biz\service\Share as sShare;
use Biz\service\theParagraph\Store as sStore;
use Doraemon\model\Category as mCategory;
use Doraemon\pockets\publicTrait\CheckConstants;
use Biz\service\brand\Brand;
use Doraemon\tools\HhzClient;
use Doraemon\tools\Log;
/**
 * @deprecated
 */
class Goods implements GoodsFields, CategoryExtendInfo
{
    use CheckConstants;

    // 商品详情页不需要返回拼团价， 但是列表页需要返回拼团价和拼团icon
    // activity_type = 9的话 返回拼团所有的数据。
    // activity_type 没有的话，默认不返回
    // redundancy 需要冗余哪个活动的数据
    // not_activity_type 什么类型不需要走优先级的逻辑
    public static function Goods($goodsIds, $fieldsGroup = self::FIELDS_GROUP_LIST, $parameter = ['activity_type' => 0, 'area_code' => 0, 'redundancy_type' => 0, 'not_activity_type' => []], $uid = 0, $status = mGoodsBasicInfo::STATUS_APP_CAN_SEE_MAP)
    {
        $params = self::verfyParams($goodsIds, $fieldsGroup);
        $activityInfo['activity_type'] = isset($parameter['activity_type']) ? $parameter['activity_type'] : ActivityInfo::ACTIVITY_TYPE_NORMAL;
        $activityInfo['redundancy_type'] = isset($parameter['redundancy_type']) ? $parameter['redundancy_type'] : 0;
        $activityInfo['not_activity_type'] = isset($parameter['not_activity_type']) ? $parameter['not_activity_type'] : [];
        $areaCode = isset($parameter['area_code']) ? $parameter['area_code'] : 0;

        $goodsInfos = self::getGoodsBasicInfos($params['goods_ids'], $status);
        if ($params['single'] && empty($goodsInfos)) {
            return ['status' => mGoodsBasicInfo::STATUS_APP_DEL];
        }
        if ($fieldsGroup == self::FIELDS_GROUP_SAME_GOODS) {
            $goodsInfos = array_filter($goodsInfos, function ($goodsInfo) {
                return mGoodsBasicInfo::STATUS_APP_MAP[$goodsInfo['status']] == mGoodsBasicInfo::STATUS_APP_NOMAL;
            });
        }
        if (empty($goodsInfos)) {
            return [];
        }
        $linkIds = self::getLinkIds($goodsInfos);

        switch ($fieldsGroup) {
            case self::FIELDS_GROUP_PARAGRAPH:
                $goodsInfos = self::getCollocations($goodsInfos);
            case self::FIELDS_GROUP_DETAIL:
                $goodsInfos = self::isFavGoods($goodsInfos, $uid, $fieldsGroup == self::FIELDS_GROUP_PARAGRAPH ? HhzClient::APPTYPE_PARAGRAPH_MINIPROGRAM : 0);
                $goodsInfos = self::getPrompt($goodsInfos, $areaCode);
                $goodsInfos = self::getSameWikiGoods($goodsInfos, $linkIds['wiki_id']);
                $goodsInfos = self::getBrandInfo($goodsInfos, $linkIds['brand_id']);
                $goodsInfos = self::getGoodsExtendInfos($goodsInfos);
                $goodsInfos = self::getServiceStatement($goodsInfos);
            case self::FIELDS_GROUP_SAME_GOODS:
                $goodsInfos = self::getShopInfo($goodsInfos, $linkIds['shop_id']);
            case self::FIELDS_GROUP_LIST:
                $goodsInfos = self::getShippingPrice($goodsInfos, $linkIds['shipping_templ_id'], $areaCode);
                $goodsInfos = self::getGoodsPriceAndStock($goodsInfos, $activityInfo);
                $goodsInfos = self::getGoodsActivitysInfos($goodsInfos, $areaCode);
                break;
            case self::FIELDS_GROUP_ORDER:
                $goodsInfos = self::getGoodsExtendInfos($goodsInfos);
                break;
            case self::FIELDS_GROUP_COMMUNITY:
                $goodsInfos = self::getGoodsPriceAndStock($goodsInfos, $activityInfo);
                $goodsInfos = self::getBrandInfo($goodsInfos, $linkIds['brand_id']);
                $goodsInfos = self::getCategoryInfo($goodsInfos, $linkIds['category_id']);
                $goodsInfos = self::getShopInfo($goodsInfos, $linkIds['shop_id']);
                break;
            case self::FIELDS_GROUP_PINTUAN_DETAIL:
            case self::FIELDS_GROUP_ONLY_DETAIL:
                $goodsInfos = self::getGoodsPriceAndStock($goodsInfos, $activityInfo);
                $goodsInfos = self::getGoodsExtendInfos($goodsInfos);
                $goodsInfos = self::getServiceStatement($goodsInfos);
                break;
            case self::FIELDS_GROUP_CART:
            case self::FIELDS_GROUP_PARAGRAPH_CART:
                $goodsInfos = self::getShippingPrice($goodsInfos, $linkIds['shipping_templ_id'], $areaCode);
                $goodsInfos = self::getGoodsPriceAndStock($goodsInfos, $activityInfo);
                break;
        }

        switch ($fieldsGroup) {
            case self::FIELDS_GROUP_PARAGRAPH:
                $goodsInfos = fGoods::formatParagraphGoodsDetail($goodsInfos);
                break;
            case self::FIELDS_GROUP_DETAIL:
                $goodsInfos = fGoods::formatGoodsDetail($goodsInfos, $activityInfo, $uid);
                break;
            case self::FIELDS_GROUP_SAME_GOODS:
                $goodsInfos = fGoods::SameGoods($goodsInfos);
                break;
            case self::FIELDS_GROUP_LIST:
                $goodsInfos = fGoods::formatGoodsList($goodsInfos);
                break;
            case self::FIELDS_GROUP_ORDER:
                $goodsInfos = fGoods::formatGoodsOrder($goodsInfos);
                break;
            case self::FIELDS_GROUP_COMMUNITY:
                $goodsInfos = fGoods::formatGoodsCommunity($goodsInfos);
                break;
            case self::FIELDS_GROUP_ONLY_DETAIL:
                $goodsInfos = fGoods::formatGooodsDetailOnly($goodsInfos);
                break;
            case self::FIELDS_GROUP_ADMIN:
                $goodsInfos = fGoods::formatGoodsAdmin($goodsInfos);
                break;
            case self::FIELDS_GROUP_CART:
                $goodsInfos = fGoods::formatCartList($goodsInfos, self::FIELDS_GROUP_CART);
                break;
            case self::FIELDS_GROUP_PARAGRAPH_CART:
                $goodsInfos = fGoods::formatCartList($goodsInfos, self::FIELDS_GROUP_PARAGRAPH_CART);
                break;
            case self::FIELDS_GROUP_PINTUAN_DETAIL:
                $goodsInfos = fGoods::formatPinTuanGoodsDetail($goodsInfos);
                break;

        }

        $version = HhzClient::getClientVersion() && version_compare(HhzClient::getClientVersion(), '3.20.0', '>=');

//        if ($version && ($fieldsGroup == self::FIELDS_GROUP_DETAIL || $fieldsGroup == self::FIELDS_GROUP_LIST)) {
//            foreach ($goodsInfos as $goodsId => $goodsInfo) {
//                $goodsInfos[$goodsId]['app_status'] = mGoodsBasicInfo::STATUS_APP_OFFLINE;
//                $goodsInfos[$goodsId]['status'] = mGoodsBasicInfo::STATUS_APP_OFFLINE;
//            }
//        }

        if ($params['single']) {
            return $goodsInfos[$goodsIds];
        } else {
            return $goodsInfos;
        }
    }


    private static function getCollocations($goodsInfos)
    {
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['collocations'] = sStore::getCollocationsByGoodsIds($goodsId);
        }
        return $goodsInfos;
    }

    private static function getPrompt($goodsInfos, $areaCode)
    {
        $listData = [];
        foreach ($goodsInfos as $goodsInfo) {
            $listData[$goodsInfo['goods_id']]['shipping_templ_id'] = $goodsInfo['shipping_templ_id'];
        }
        $suprotShipping = ShippingTempl::checkGoodsSupportShipping($listData, $areaCode);
        foreach ($goodsInfos as $k => $goodsInfo) {
            $goodsInfos[$k]['prompt'] = in_array($goodsInfo['goods_id'], $suprotShipping['support_goods']) ? '' : '抱歉，此商品无法配送至当前地区';
            $goodsInfos[$k]['goods_tip'] = in_array($goodsInfo['goods_id'], $suprotShipping['support_goods']) ? '' : '由于「the Paragraph 节选」仍在试运营阶段，该商品收货地址仅限' . $suprotShipping['support_area'][$goodsInfo['goods_id']] . '，其他地区将逐渐开放，敬请谅解。';
        }
        return $goodsInfos;
    }

    private static function getCategoryInfo($goodsInfos, $categoryIds)
    {
        $categoryInfos = mCategory::selectCategorys($categoryIds);
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['category_info'] = isset($categoryInfos[$goodsInfo['last_category_id']]) ? $categoryInfos[$goodsInfo['last_category_id']] : [];
        }
        return $goodsInfos;
    }


    private static function getShopInfo($goodsInfos, $shopIds)
    {
        $shopInfos = ShopInfo::getShopInfoList($shopIds, 'app');
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['shop_info'] = $shopInfos[$goodsInfo['shop_id']];
        }
        return $goodsInfos;
    }

    private static function getServiceStatement($goodsInfos)
    {
        $shopIds = array_column($goodsInfos, 'shop_id');
        $shopServiceStatement = ShopInfo::admShopServiceStatement($shopIds);
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['service_statement'] = $serviceStatements = [];
            $goodsInfos[$goodsId]['service_statement_img'] = '';
            if (isset($shopServiceStatement[$goodsInfo['shop_id']][$goodsInfo['category_id']])) foreach ($shopServiceStatement[$goodsInfo['shop_id']][$goodsInfo['category_id']] as $item) {
                if ($item['is_selected'] == 1) {
                    $goodsInfos[$goodsId]['service_statement'][] = self::SERVICE_STATEMENT_BASEED_CATE_ID[$goodsInfo['category_id']][$item['id']];
                    $serviceStatements[] = $item['id'];
                }
            }
            sort($serviceStatements);
            $serviceStatementImg = $serviceStatements && isset(self::FURNITURE_SERVICE_STATEMENT_PIC_MAP[implode('', $serviceStatements)]) && self::FURNITURE_SERVICE_STATEMENT_PIC_MAP[implode('', $serviceStatements)] !== null ? self::FURNITURE_SERVICE_STATEMENT_PIC_MAP[implode('', $serviceStatements)] : '';
            $goodsInfos[$goodsId]['service_statement_img'] = $serviceStatementImg;
        }
        return $goodsInfos;
    }

    private static function getBrandInfo($goodsInfos, $brandIds)
    {
        if ($brandIds) {
            $brandInfos = Brand::getBrandListByIds4App($brandIds);
        } else {
            $brandInfos = [];
        }
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            if ($goodsInfo['brand_id'] && isset($brandInfos[$goodsInfo['brand_id']])) {
                $goodsInfos[$goodsId]['brand_info'] = $brandInfos[$goodsInfo['brand_id']];
            } else {
                $goodsInfos[$goodsId]['brand_info'] = null;
            }
        }
        return $goodsInfos;
    }


    private static function getLinkIds($goodsInfos)
    {
        $linkIds = [
            'wiki_id' => [],
            'brand_id' => [],
            'shop_id' => [],
            'shipping_templ_id' => [],
            'category_id' => []
        ];
        foreach ($goodsInfos as $goodsInfo) {
            if ($goodsInfo['wiki_id']) {
                $linkIds['wiki_id'][] = $goodsInfo['wiki_id'];
            }
            if ($goodsInfo['brand_id']) {
                $linkIds['brand_id'][] = $goodsInfo['brand_id'];
            }
            $linkIds['shop_id'][] = $goodsInfo['shop_id'];
            $linkIds['shipping_templ_id'][] = $goodsInfo['shipping_templ_id'];
            $linkIds['category_id'][] = $goodsInfo['last_category_id'];
        }
        return [
            'wiki_id' => array_unique($linkIds['wiki_id']),
            'brand_id' => array_unique($linkIds['brand_id']),
            'shop_id' => array_unique($linkIds['shop_id']),
            'shipping_templ_id' => array_unique($linkIds['shipping_templ_id']),
            'category_id' => array_unique($linkIds['category_id'])
        ];
    }


    private static function isFavGoods($goodsInfos, $uid, $appSource = 0)
    {
        if ($uid) {
            $is_favs = ShopFavorite::is_favorited($uid, array_keys($goodsInfos), ShopFavorite::TYPE_GOODS, $appSource);
            foreach ($goodsInfos as $goodsId => $goodsInfo) {
                $goodsInfos[$goodsId]['is_fav'] = $is_favs[$goodsId];
            }

        } else {
            foreach ($goodsInfos as $goodsId => $goodsInfo) {
                $goodsInfos[$goodsId]['is_fav'] = 0;
            }
        }
        return $goodsInfos;
    }

    private static function getGoodsActivitysInfos($goodsInfos, $areaCode)
    {
        $shopData = [];
        foreach ($goodsInfos as $goodsInfo) {
            $shopData[$goodsInfo['shop_id']][] = $goodsInfo['goods_id'];
        }
        if ($areaCode) {
            //满包邮
            $fullShippingFrees = sFullShipping::quickGetFormatInfos($shopData, $areaCode, true);
            foreach ($goodsInfos as $goodsId => $goodsInfo) {
                if (isset($fullShippingFrees[$goodsInfo['shop_id']][$goodsId]) && !empty($fullShippingFrees[$goodsInfo['shop_id']][$goodsId])) {
                    $goodsInfos[$goodsId]['activity_infos'][] = $fullShippingFrees[$goodsInfo['shop_id']][$goodsId];
                }
            }
        }
        return $goodsInfos;
    }

//= ['activity_type' => 0, 'redundancy_type' => 0, 'notActivityType' => []]
    private static function getGoodsPriceAndStock($goodsInfos, $activityInfo)
    {
        $goodsIds = array_keys($goodsInfos);
        $skuInfos = Sku::Sku($goodsIds, Sku::FIELDS_GROUP_GOODS_DETAIL, $activityInfo);
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId] = array_merge($goodsInfo, isset($skuInfos[$goodsId]) ? $skuInfos[$goodsId] : []);
        }
        return $goodsInfos;
    }

    private static function getSameWikiGoods($goodsInfos, $wikiIds)
    {
        if ($wikiIds) {
            list($wikiGoodsIds, $noCacheKeys) = cWikiGoods::mGetItems($wikiIds);
            if ($noCacheKeys) {
                $mWikiGoodsIds = mGoodsBasicInfo::getSameGoodsIdsByWikiIds($noCacheKeys);
                foreach ($noCacheKeys as $wikiId) {
                    if (!isset($mWikiGoodsIds[$wikiId])) {
                        $mWikiGoodsIds[$wikiId] = [];
                    }
                }
                cWikiGoods::mSetItems($mWikiGoodsIds);
                $wikiGoodsIds = $wikiGoodsIds + $mWikiGoodsIds;
            }
            foreach ($goodsInfos as $goodsId => $goodsInfo) {
                if (isset($wikiGoodsIds[$goodsInfo['wiki_id']]) && count($wikiGoodsIds[$goodsInfo['wiki_id']]) > 1) {
                    $sameGoodsIds = array_filter($wikiGoodsIds[$goodsInfo['wiki_id']],
                        function ($wikiGoodsId) use ($goodsId) {
                            return $wikiGoodsId != $goodsId;
                        });
                    $sameGoods = self::Goods($sameGoodsIds, self::FIELDS_GROUP_SAME_GOODS);
                    $goodsInfos[$goodsId]['same_goods'] = $sameGoods;
                } else {
                    $goodsInfos[$goodsId]['same_goods'] = null;
                }
            }
        } else {
            $goodsInfos = array_map(function ($goodsInfo) {
                $goodsInfo['same_goods'] = null;
                return $goodsInfo;
            }, $goodsInfos);
        }
        return $goodsInfos;
    }

    /**
     * @note 商品有多个sku，运费取体积最小的sku计算，体积最小的sku无库存时，取其他有库存且体积(单位)最小的sku计算。如果所有sku都没有库存，则还是按照体积(单位)最小的sku计算运费
     * @param $goodsInfos
     * @param $shippingTemplIds
     * @param $areaCode
     * @return mixed
     */
    private static function getShippingPrice($goodsInfos, $shippingTemplIds, $areaCode)
    {
        $goodsIds = array_keys($goodsInfos);
        $skuInfos = Sku::Sku($goodsIds, Sku::FIELDS_GROUP_SKU_INFO);

        $shippingTemplIds = [];
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            if (isset($skuInfos[$goodsId])) {
                $skuInfo = $skuInfos[$goodsId];
                //过滤无库存的sku
                $partShipping = array_filter($skuInfo, function ($v) {
                    return $v['stock'] > 0;
                });
                $partShipping = empty($partShipping) ? $skuInfo : $partShipping;

                //参数结构
                $shippingTemplIds[$goodsInfo['shipping_templ_id']][$goodsId]['weight'] = !empty($partShipping) ? min(array_column($partShipping, 'weight')) : 0;
                $shippingTemplIds[$goodsInfo['shipping_templ_id']][$goodsId]['volume'] = !empty($partShipping) ? min(array_column($partShipping, 'volume')) : 0;
            }
        }
        $shippingPrice = ShippingTempl::quickGetShippingInfos($shippingTemplIds, $areaCode);
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['shipping_price'] = $shippingPrice[$goodsId];
        }
        return $goodsInfos;
    }

    private static function getGoodsExtendInfos($goodsInfos)
    {
        $goodsIds = array_keys($goodsInfos);
        list($goodsExtendInfos, $noCacheKeys) = cGoodsExtendInfo::mGetItems($goodsIds);
        if ($noCacheKeys) {
            $mGoodsExtendInfos = mGoodsExtendInfo::getExtendInfosByGoodsIds($noCacheKeys);
            cGoodsExtendInfo::mSetItems($mGoodsExtendInfos);
            $goodsExtendInfos = $goodsExtendInfos + $mGoodsExtendInfos;
        }
        foreach ($goodsInfos as $goodsId => $goodsInfo) {
            $goodsInfos[$goodsId]['extend_info'] = $goodsExtendInfos[$goodsId];
        }
        return $goodsInfos;
    }

    public static function getGoodsBasicInfos($goodsIds, $status = mGoodsBasicInfo::STATUS_APP_CAN_SEE_MAP)
    {
        list($goodsBaseInfos, $noCacheKeys) = cGoodsBaseInfo::mGetItems($goodsIds);
        if ($noCacheKeys) {
            $mGoodsBaseInfos = mGoodsBasicInfo::getGoodsInfoByGoodIds($noCacheKeys, $status);
            cGoodsBaseInfo::mSetItems($mGoodsBaseInfos);
            $goodsBaseInfos = $goodsBaseInfos + $mGoodsBaseInfos;
        }
        return $goodsBaseInfos;
    }

    private static function verfyParams($goodsIds, $fieldsGroup)
    {
        $verfyResult = [];
        try {
            if (is_array($goodsIds)) {
                $verfyResult['goods_ids'] = array_filter($goodsIds, function ($goodsId) {
                    return is_numeric($goodsId);
                });
                $verfyResult['single'] = false;
            } elseif (is_numeric($goodsIds)) {
                $verfyResult['goods_ids'] = [$goodsIds];
                $verfyResult['single'] = true;
            } else {
                throw new \Exception("请求参数异常");
            }
            if (!self::checkConstants(self::_CONST_FIELDS_GROUP_PREFIX, $fieldsGroup)) {
                throw new \Exception("请求参数异常");
            } else {
                $verfyResult['fields_group'] = $fieldsGroup;
            }
            return $verfyResult;
        } catch (\Exception $e) {
            $trace = [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $e->getMessage(),
            ];
            Log::info('商品参数校验错误信息', compact('goodsIds', 'fieldsGroup', 'verfyResult', 'trace'));
            throw new \Exception("请求参数异常");
        }

    }

    public static function admGetAddCartNums($goodsId)
    {
        list($cacheDatas, $noCacheKeys) = cSkuBase::pHGetAllItems([$goodsId]);
        if ($noCacheKeys) {
            $skuBaseInfos = mGoodsSku::getSkusByGoodsIds($noCacheKeys);
            cSkuBase::pHMSetItems($skuBaseInfos);
            $cacheDatas = $skuBaseInfos;
        }
        $skuIds = isset($cacheDatas[$goodsId]) ? array_column($cacheDatas[$goodsId], 'id') : [];

        return $skuIds ? Cart::admGetAllNums($skuIds) : 0;
    }

    public static function goodsShare($goodsList)
    {
        $share = [];
        $goodsLists = mGoodsBasicInfo::select('*', ['goods_id' => $goodsList]);
        foreach ($goodsLists as $_gk => &$_gv) {
            $brands[$_gv['id']] = $_gv['brand_id'];
        }
        $brandInfos = Brand::getBrandListByIds4App(array_values($brands));
        foreach ($goodsLists as $_gkey => &$_gval) {
            foreach ($brandInfos as $_bk => &$_bv) {
                if ($_bv['id'] == $_gval['brand_id']) {
                    $goodsLists[$_gkey]['brand_info']['name'] = $_bv['name'];
                }
            }
            $share[$_gval['goods_id']] = sShare::getGoodsShare($goodsLists[$_gkey]);
        }
        return $share;
    }

    public static function goodsPintuanShare($goodsLists, $teamId)
    {
        $share = [];
        foreach ($goodsLists as $_gkey => &$_gval) {
            $share[$_gval['goods_id']] = sShare::getGoodsPintuanShare($goodsLists[$_gkey], $teamId);
        }
        return $share;
    }


    public static function goodsBrands($goodsList)
    {
        $goodsLists = [];
        $goodsLists = mGoodsBasicInfo::select('*', ['goods_id' => $goodsList]);
        foreach ($goodsLists as $_gk => &$_gv) {
            $brands[$_gv['goods_id']] = $_gv['brand_id'];
        }
        $brandInfos = Brand::getBrandListByIds4App(array_values($brands));
        foreach ($goodsLists as $_gkey => &$_gval) {
            foreach ($brandInfos as $_bk => &$_bv) {
                if ($_bv['id'] == $_gval['brand_id']) {
                    $goodsLists[$_gkey]['brand_info']['name'] = $_bv['name'];
                }
            }
        }
        return $goodsLists;
    }

}
